//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "pseudo.h"
#include "cprocess.h"
#include "cthread.h"
#include "cevent.h"
#include "cmutex.h"
#include "csharedmemory.h"
#include "helper.h"
#include <aura.h>

#define _PAGE_SIZE          (1u << 12)
#define IS_PAGE_ALIGNED(va) (0 == ((va) & (_PAGE_SIZE -1)))

CARAPI CPseudoKernel::System_GetTime(
        /* [out] */ SystemTime * pSystemTime)
{
    if (NULL == pSystemTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetTime((Aura_SystemTime *)pSystemTime);

}

CARAPI CPseudoKernel::System_SetTime(
        /* [in] */ SystemTime * pSystemTime)
{
    if (NULL == pSystemTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_SetTime((Aura_SystemTime *)pSystemTime);
}

CARAPI CPseudoKernel::System_QueryPerformanceCounter(
        /* [out] */ Int64 * pCounter)
{
    if (NULL == pCounter) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_QueryPerformanceCounter(pCounter);
}

CARAPI CPseudoKernel::System_QueryPerformanceFrequency(
        /* [out] */ Int64 * pFrequency)
{
    if (NULL == pFrequency) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_QueryPerformanceFrequency(pFrequency);
}

CARAPI CPseudoKernel::System_GetElapsedTime(
        /* [out] */ Millisecond32 * pTime)
{
    if (NULL == pTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetElapsedTime((Aura_Millisecond32 *)pTime);
}

CARAPI CPseudoKernel::System_GetIdleTime(
        /* [out] */ Millisecond32 * pTime)
{
    if (NULL == pTime) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetIdleTime((Aura_Millisecond32 *)pTime);
}

CARAPI CPseudoKernel::System_Reboot()
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_GetAllProcesses(
        /* [out] */ IObjectEnumerator ** ppProcesses)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_GetMemorySizes(
        /* [out] */ Int32 * pTotalPhysicalMemorySize,
        /* [out] */ Int32 * pAvailablePhysicalMemorySize)
{
    if ((NULL == pTotalPhysicalMemorySize)
        && (NULL == pAvailablePhysicalMemorySize)) {
        return E_INVALID_ARGUMENT;
    }

    return AuraSystem_GetMemorySizes(
                    (Aura_Int32 *)pTotalPhysicalMemorySize,
                    (Aura_Int32 *)pAvailablePhysicalMemorySize);
}

CARAPI CPseudoKernel::System_GetDomainHostManager(
        /* [out] */ IHostingManager ** ppHostingManager)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_TryWaitForAnyEvent(
        /* [in] */ const BufferOf<IEvent *> * pEvents,
        /* [in] */ Millisecond32 msTimeout,
        /* [out] */ WaitResult * pResult,
        /* [out] */ Int32 * pIndex,
        /* [out] */ EventState * pState)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_RequestIntrestedEvent(
        /* [in] */ SystemEvents intrestedEvents,
        /* [out] */ IEvent * * ppEvent)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::System_GetEnvironMutex(
        /* [out] */ IMutex ** ppEnvMutex)
{
    if (NULL == ppEnvMutex) {
        return E_INVALID_ARGUMENT;
    }

    return CMutex::New(ppEnvMutex);
}

CARAPI CPseudoKernel::System_DebugPrint(
        /* [in]  */ const wchar_t * str)
{
    Aura_putws((const Aura_PWChar)str);
    return NOERROR;
}

CARAPI CPseudoKernel::System_DebugErrorPrint(
        /* [in]  */ const wchar_t * str)
{
    return AuraSystem_ErrorPrint((Aura_PWChar)str);
}

// --------------------------------------------------------
CARAPI CPseudoKernel::Process_CreateWithUnstarted(
        /* [out] */ IProcess ** ppProcess)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI_(IProcess *) CPseudoKernel::Process_GetCurrent()
{
    return Helper_Process_GetCurrent();
}

CARAPI_(ProcessId) CPseudoKernel::Process_GetCurrentId()
{
    return AuraProcess_GetCurrentId();
}

CARAPI_(void) CPseudoKernel::Process_ExitCurrent(
        /* [in] */ ExitCode exitCode)
{
    GET_CPROCESS()->Helper_ExitCurrent(exitCode);
    assert(0);
}

CARAPI CPseudoKernel::Process_LoadModule(
        /* [in] */ WString name,
        /* [in] */ ModuleLoadFlags flags,
        /* [out] */ IModule ** ppModule)
{
    if (name.IsNullOrEmpty()
       || (NULL == ppModule)) {
        return E_INVALID_ARGUMENT;
    }
    CProcess * pProcess = static_cast<CProcess *>(Helper_Process_GetCurrent());
    return pProcess->Helper_LoadModule(name, flags, ppModule);
}

CARAPI CPseudoKernel::Process_FlushInstructionCache(
        /* [in] */ Address baseAddr,
        /* [in] */ MemorySize size)
{
    FixMe("Not Implemented yet.");
    return E_NOT_IMPLEMENTED;
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Thread_Create(
        /* [in] */ Address entry,
        /* [in] */ Address userEntry,
        /* [in] */ Address userArgs,
        /* [in] */ ThreadCreationFlags flags,
        /* [out] */ IThread ** ppThread)
{
    IThread * pThread = NULL;
    ECode ec = NOERROR;

    if (NULL == userEntry) {
        return E_INVALID_ARGUMENT;
    }

    ec = CThread::New(entry,
                    userEntry, userArgs,
                    flags,
                    &pThread);
    if (FAILED(ec)) {
        goto E_FAIL_EXIT;
    }
    if (NULL != ppThread) {
        *ppThread = pThread;
    }
    else {
        pThread->Release();
    }

    return NOERROR;

E_FAIL_EXIT:
    if (NULL != pThread) {
        delete pThread;
    }
    return ec;
}

CARAPI_(IThread *) CPseudoKernel::Thread_GetCurrent()
{
    return Helper_Thread_GetCurrent();
}

CARAPI_(ThreadId) CPseudoKernel::Thread_GetCurrentId()
{
    return AuraThread_GetCurrentId();
}

CARAPI_(Boolean) CPseudoKernel::Thread_CurrentIsMain()
{
    return Helper_Thread_IsMain(Helper_Thread_GetCurrent());
}

CARAPI_(void) CPseudoKernel::Thread_QuitCurrent(
        /* [in] */ QuitCode quitCode)
{
    IThread * pThread = Helper_Thread_GetCurrent();

    if (Helper_Thread_IsMain(pThread)) {
        GET_CPROCESS()->Helper_ExitCurrent(quitCode);
    }
    else {
        CTHREAD(pThread)->Helper_QuitAsCurrent(quitCode);
    }
    assert(0);
}

CARAPI CPseudoKernel::Thread_Sleep(
        /* [in] */ Millisecond32 msTimeout,
        /* [out] */ WaitResult * pResult)
{
    Aura_WaitResult wr;

    if (0 == msTimeout) {
        AuraThread_Sleep(0, &wr);
        return NOERROR;
    }

    THREAD_START_SLEEP()
    {
        AuraThread_Sleep(msTimeout, &wr);
    }
    THREAD_END_SLEEP;

    if (NULL != pResult) {
        *pResult = wr;
    }

    return NOERROR;
}

CARAPI CPseudoKernel::Thread_Yield()
{
    AuraThread_Yield();
    return NOERROR;
}

// --------------------------------------------------------

CARAPI CPseudoKernel::VirtualMemory_Map(
        /* [in] */ Address vBaseAddr,
        /* [in] */ MemorySize size,
        /* [in] */ MemoryMapFlags flags,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Address *pBaseAddr)
{
    if ((size <= 0)
        || !IS_PAGE_ALIGNED(vBaseAddr)
        || !IS_PAGE_ALIGNED(size)
        || (NULL == pBaseAddr)
        || ((flags & MemoryMap_UpGrow)
         && (flags & MemoryMap_DownGrow))) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Map(vBaseAddr,
                                size,
                                flags,
                                protect,
                               (Aura_Address *)pBaseAddr);
}

CARAPI CPseudoKernel::VirtualMemory_Query(
        /* [in] */ Address vAddress,
        /* [out] */ Address *pBaseAddr,
        /* [out] */ MemorySize *pSize)
{
    if ((NULL == pBaseAddr)
        && (NULL == pSize)) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Query(vAddress,
                           (Aura_Address *)pBaseAddr,
                           (Aura_MemorySize *)pSize);
}

CARAPI CPseudoKernel::VirtualMemory_SetProtection(
        /* [in] */ Address vBaseAddr,
        /* [in] */ MemorySize size,
        /* [in] */ MemoryProtection protect)
{
    if (size <= 0) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_SetProtection(vBaseAddr, size, protect);
}

CARAPI CPseudoKernel::VirtualMemory_CheckProtection(
        /* [in] */ Address vAddress,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Boolean *pIsValid)
{
    if (NULL == pIsValid) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_CheckProtection(vAddress, protect, pIsValid);
}

CARAPI CPseudoKernel::VirtualMemory_Commit(
        /* [in] */ Address vAddress)
{
    return AuraVirtualMemory_Commit(vAddress);
}

CARAPI CPseudoKernel::VirtualMemory_IoRemap(
        /* [in] */ Address virtualAddr,
        /* [in] */ MemorySize size,
        /* [in] */ Address physicalAddr,
        /* [in] */ MemoryMapFlags flags,
        /* [in] */ MemoryProtection protect,
        /* [out] */ Address *pVirtualAddr)
{
    return AuraVirtualMemory_IORemap(virtualAddr,
                            size,
                            physicalAddr,
                            flags,
                            protect,
                           (Aura_Address *)pVirtualAddr);
}

CARAPI CPseudoKernel::VirtualMemory_Unmap(
        /* [in] */ Address vBaseAddr,
        /* [in] */ MemorySize size)
{
    if (size <= 0) {
        return E_INVALID_ARGUMENT;
    }

    return AuraVirtualMemory_Unmap(vBaseAddr, size);
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Mutex_Create(
        /* [out] */ IMutex ** ppMutex)
{
    if (NULL == ppMutex) {
        return E_INVALID_ARGUMENT;
    }

    return CMutex::New(ppMutex);
}

CARAPI CPseudoKernel::Mutex_Create(
        /* [in] */ WString name,
        /* [out] */ IMutex ** ppMutex,
        /* [out] */ Boolean * pbAlreadyExisted)
{
    IMutex * pMutex = NULL;
    Boolean bAlreadyEixsted = FALSE;
    ECode ec = NOERROR;

    if (NULL == ppMutex) {
        return E_INVALID_ARGUMENT;
    }

    ec = CMutex::New(&pMutex);
    if (FAILED(ec)) {
        goto E_FAIL_EXIT;
    }
    ec = RegisterRunningObject(name, pMutex);
    if (FAILED(ec)) {
        if (E_ALREADY_EXIST != ec) {
            goto E_FAIL_EXIT;
        }
        bAlreadyEixsted = TRUE;
    }

    *ppMutex = pMutex;
    if (NULL != pbAlreadyExisted) {
        *pbAlreadyExisted = bAlreadyEixsted;
    }

    return NOERROR;

E_FAIL_EXIT:
    if (NULL != pMutex) {
        pMutex->Release();
    }
    return ec;
}

CARAPI CPseudoKernel::Event_Create(
        /* [in] */ Boolean bManualReset,
        /* [in] */ EventState initState,
        /* [out] */ IEvent ** ppEvent)
{
    if (NULL == ppEvent) {
        return E_INVALID_ARGUMENT;
    }

    return CEvent::New(bManualReset, initState, ppEvent);
}

CARAPI CPseudoKernel::Event_Create(
        /* [in] */ WString name,
        /* [in] */ Boolean bManualReset,
        /* [in] */ EventState initState,
        /* [out] */ IEvent ** ppEvent,
        /* [out] */ Boolean * pbAlreadyExisted)
{
    IEvent * pEvent = NULL;
    Boolean bAlreadyEixsted = FALSE;
    ECode ec = NOERROR;

    if (NULL == ppEvent) {
        return E_INVALID_ARGUMENT;
    }

    ec = CEvent::New(bManualReset, initState, &pEvent);
    if (FAILED(ec)) {
        goto E_FAIL_EXIT;
    }
    ec = RegisterRunningObject(name, pEvent);
    if (FAILED(ec)) {
        if (E_ALREADY_EXIST != ec) {
            goto E_FAIL_EXIT;
        }
        bAlreadyEixsted = TRUE;
    }

    *ppEvent = pEvent;
    if (NULL != pbAlreadyExisted) {
        *pbAlreadyExisted = bAlreadyEixsted;
    }

    return NOERROR;

E_FAIL_EXIT:
    if (NULL != pEvent) {
        pEvent->Release();
    }
    return ec;
}

CARAPI CPseudoKernel::Condition_Create(
        /* [out] */ ICondition ** ppCondition)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::Condition_Create(
        /* [in] */ WString name,
        /* [out] */ ICondition ** ppCondition,
        /* [out] */ Boolean * pbAlreadyExisted)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::ReaderWriterLock_Create(
        /* [out] */ IReaderWriterLock ** ppRwlock)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::ReaderWriterLock_Create(
        /* [in] */ WString name,
        /* [out] */ IReaderWriterLock ** ppRwlock,
        /* [out] */ Boolean * pbAlreadyExisted)
{
    FixMe("Not implemented yet.");
    return E_NOT_IMPLEMENTED;
}

CARAPI CPseudoKernel::SharedMemory_Create(
        /* [in] */ WString name,
        /* [in] */ MemorySize memorySize,
        /* [in] */ Boolean bCommit,
        /* [out] */ ISharedMemory ** ppSharedMemory,
        /* [out] */ Boolean * pbAlreadyExisted)
{
    Boolean bAlreadyExisted = FALSE;
    ISharedMemory * pSharedMemory = NULL;
    ECode ec = NOERROR;

    if (name.IsNullOrEmpty()
        || (NULL == ppSharedMemory)) {
        return E_INVALID_ARGUMENT;
    }

    ec = CSharedMemory::New(name, memorySize, bCommit,
                          &pSharedMemory,
                          &bAlreadyExisted);
    if (FAILED(ec)) {
        goto E_FAIL_EXIT;
    }

    ec = RegisterRunningObject(name, pSharedMemory);
    if (FAILED(ec)) {
        if (E_ALREADY_EXIST != ec) {
            goto E_FAIL_EXIT;
        }
		ec = NOERROR;
        bAlreadyExisted = TRUE;
    }

    if (NULL != pbAlreadyExisted) {
        *pbAlreadyExisted = bAlreadyExisted;
    }
    *ppSharedMemory = pSharedMemory;

    return NOERROR;

E_FAIL_EXIT:
    if (NULL != pSharedMemory) {
        pSharedMemory->Release();
    }
    return ec;
}

// --------------------------------------------------------

CARAPI CPseudoKernel::Tls_AcquireSlot(
        /* [in] */ ThreadLocalSlotType type,
        /* [out] */ Int32 * pSlotIndex)
{
    return Helper_TlsMgr_AcquireSlot(type, pSlotIndex);
}

CARAPI CPseudoKernel::Tls_RelinquishSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Int32> * pUsedPtrs)
{
     return Helper_TlsMgr_RelingquishSlot(slotIndex, pUsedPtrs);
}

CARAPI CPseudoKernel::Tls_CleanupSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Int32> * pUsedPtrs)
{
    return Helper_TlsMgr_CleanupSlot(slotIndex, pUsedPtrs);
}

CARAPI CPseudoKernel::Tls_GetValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [out] */ PVoid * ppValue)
{
    return Helper_TlsMgr_GetValue(type, slotIndex, ppValue);
}

CARAPI CPseudoKernel::Tls_SetValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [in] */ PVoid pValue)
{
    return Helper_TlsMgr_SetValue(type, slotIndex, pValue);
}

